﻿
Public Class Send_Agreement
    Dim SP_REC As New ArrayList    '接收电台收到的信息队列
    Dim rec_datas As Byte() = Nothing

    Private Function Get_CRC16(ByVal Crc16_num As Byte(), ByVal start As Integer, ByVal ends As Integer) As Integer    'CRC校验
        Dim i, j As Integer
        Dim crc As Integer
        crc = &HFFFF
        For i = start To ends - 1
            crc = crc Xor Crc16_num(i)
            For j = 0 To 7 Step 1
                If (crc And &H1) > 0 Then
                    crc = crc >> 1
                    crc = crc Xor &HA001

                Else
                    crc = crc >> 1
                End If
            Next j
        Next i
        Return crc
    End Function


    ''' <summary>
    ''' 生成中心协议数据帧
    ''' </summary>
    ''' <param name="types">设备类型</param>
    ''' <param name="oper">设备功能</param>
    ''' <param name="ids">设备ID</param>
    ''' <param name="datas">要带入的数据，没有则为空</param>
    ''' <returns></returns>
    Public Function Make_AgreementCenter(ByVal types As Byte, ByVal oper As Byte, ByVal ids As Integer(), ByVal datas As Byte()) As Byte()
        Dim add_lens As Integer = 7    '头尾固定长度
        Dim id_len As Integer = ids.Length * 2
        Dim datas_len As Integer
        If IsNothing(datas) = False Then
            datas_len = datas.Length
        Else
            datas_len = 0
        End If
        Dim yy As Integer = 0, i As Integer = 0, j As Integer = 0
        Dim Send_Msg(add_lens + id_len + datas_len + 2) As Byte
        Send_Msg(0) = &H18
        Send_Msg(1) = &H28
        Send_Msg(2) = types + &H80
        Send_Msg(3) = (id_len + datas_len + 2) Mod 256
        Send_Msg(4) = oper
        Send_Msg(5) = ids.Length
        For i = 0 To id_len - 1
            Send_Msg(6 + i) = ids(yy) \ 256
            i += 1
            Send_Msg(6 + i) = ids(yy) Mod 256
            yy += 1
        Next
        j = 6 + i
        If IsNothing(datas) = False Then
            For j = 6 + i To 6 + i + datas.Length - 1
                Send_Msg(j) = datas(j - (6 + i))
            Next
        End If

        Dim CRC As Integer = Get_CRC16(Send_Msg, 0, j)
        Send_Msg(j) = CRC \ 256
        Send_Msg(j + 1) = CRC Mod 256
        Send_Msg(j + 2) = &H58
        ReDim Preserve Send_Msg(Send_Msg.Length - 2)
        Return Send_Msg
    End Function


    ''' <summary>
    ''' 生成节点协议数据帧
    ''' </summary>
    ''' <param name="types">设备类型</param>
    ''' <param name="oper">设备功能</param>
    ''' <param name="ids">设备ID</param>
    ''' <param name="datas">要带入的数据，没有则为空</param>
    ''' <returns></returns>
    Public Function Make_AgreementNode(ByVal types As Byte, ByVal oper As Byte, ByVal ids As Integer(), ByVal datas As Byte()) As Byte()
        Dim add_lens As Integer = 7    '头尾固定长度
        Dim id_len As Integer = ids.Length * 2
        Dim datas_len As Integer
        If IsNothing(datas) = False Then
            datas_len = datas.Length
        Else
            datas_len = 0
        End If
        Dim yy As Integer = 0, i As Integer = 0, j As Integer = 0
        Dim Send_Msg(add_lens + id_len + datas_len + 2 + 1) As Byte
        Send_Msg(0) = &H18
        Send_Msg(1) = &H28
        Send_Msg(2) = types
        Send_Msg(3) = (id_len + datas_len + 2 + 1) Mod 256
        Send_Msg(4) = oper
        Send_Msg(5) = ids.Length
        For i = 0 To id_len - 1
            Send_Msg(6 + i) = ids(yy) \ 256
            i += 1
            Send_Msg(6 + i) = ids(yy) Mod 256
            yy += 1
        Next
        Send_Msg(6 + i) = &HFF
        j = 7 + i
        If IsNothing(datas) = False Then
            For j = 7 + i To 7 + i + datas.Length - 1
                Send_Msg(j) = datas(j - (7 + i))
            Next
        End If

        Dim CRC As Integer = Get_CRC16(Send_Msg, 0, j)
        Send_Msg(j) = CRC \ 256
        Send_Msg(j + 1) = CRC Mod 256
        Send_Msg(j + 2) = &H58
        ReDim Preserve Send_Msg(Send_Msg.Length - 2)
        Return Send_Msg
    End Function



    ''' <summary>
    ''' 读取协议内容
    ''' </summary>
    ''' <param name="rec_data">需要解析的数组</param>
    ''' <returns>符合协议的数组存储到LIST中，一条符合的就是一个LIST项</returns>
    Public Function Read_Agreement(ByVal rec_data As Byte()) As List(Of Byte()) ' As Byte()  '提取符合协议的控制内容
        Dim Receive_Msg As New List(Of Byte())
        SP_REC.AddRange(rec_data)
        While SP_REC.Count > 11    '至少包含11字节，2字节头，1字节type，1字节len，1字节oper，1字节编号长度，2字节编号，2字节CRC校验，1字节尾
            If SP_REC(0) = &H18 And SP_REC(1) = &H28 Then   '头判断
                Dim len As Integer = SP_REC(3)  '获得收到数据长度
                If SP_REC.Count < len + 7 Then  '判断数据长度是否完整，若小于最小长度则数据分析完毕
                    SP_REC.RemoveAt(0)
                    Continue While
                End If
                Dim crc16 As Integer, ls(len + 3) As Byte
                For i = 0 To ls.Length - 1
                    ls(i) = SP_REC(i)
                Next
                crc16 = Get_CRC16(ls, 0, ls.Length)
                If crc16 \ 256 <> SP_REC(ls.Length) Or crc16 Mod 256 <> SP_REC(ls.Length + 1) Then
                    SP_REC.RemoveAt(0)
                    Continue While
                End If
                If SP_REC(ls.Length + 2) <> &H58 Then
                    SP_REC.RemoveAt(0)
                    Continue While
                End If
                ReDim rec_datas(ls.Length + 2)
                SP_REC.CopyTo(0, rec_datas, 0, ls.Length + 3)     '获得一条完整语句
                Receive_Msg.Add(rec_datas)
                SP_REC.RemoveRange(0, ls.Length + 2)              '缓存中移除这条语句
            Else
                SP_REC.RemoveAt(0)  '若不是头则移除
            End If
        End While
        Return Receive_Msg
    End Function

    ''' <summary>
    ''' 读取协议内容
    ''' </summary>
    ''' <param name="rec_data">需要解析的数组</param>
    ''' <returns>符合协议的数组存储到LIST中，一条符合的就是一个LIST项</returns>
    Public Function Read_CMDAgreement(ByVal rec_data As Byte()) As List(Of Byte()) ' As Byte()  '提取符合协议的控制内容
        Dim Receive_Msg As New List(Of Byte())
        SP_REC.AddRange(rec_data)
        Dim movepos As Integer = 2
        While SP_REC.Count > 13    '至少包含13字节，2字节无线模块编号，2字节头，1字节type，1字节len，1字节oper，1字节编号长度，2字节编号，2字节CRC校验，1字节尾
            If SP_REC(0 + movepos) = &H18 And SP_REC(1 + movepos) = &H28 Then   '头判断
                Dim len As Integer = SP_REC(3 + movepos)  '获得收到数据长度
                If SP_REC.Count < len + 7 + movepos Then  '判断数据长度是否完整，若小于最小长度则数据分析完毕
                    SP_REC.RemoveAt(0)
                    Continue While
                End If
                Dim crc16 As Integer, ls(len + 3) As Byte
                For i = 0 To ls.Length - 1
                    ls(i) = SP_REC(i + movepos)
                Next
                crc16 = Get_CRC16(ls, 0, ls.Length)
                If crc16 \ 256 <> SP_REC(ls.Length + movepos) Or crc16 Mod 256 <> SP_REC(ls.Length + 1 + movepos) Then
                    SP_REC.RemoveAt(0)
                    Continue While
                End If
                If SP_REC(ls.Length + 2 + movepos) <> &H58 Then
                    SP_REC.RemoveAt(0)
                    Continue While
                End If
                ReDim rec_datas(ls.Length + 2 + movepos)
                SP_REC.CopyTo(0, rec_datas, 0, ls.Length + 3 + movepos)     '获得一条完整语句
                Receive_Msg.Add(rec_datas)
                SP_REC.RemoveRange(0, ls.Length + 2 + movepos)              '缓存中移除这条语句
            Else
                SP_REC.RemoveAt(0)  '若不是头则移除
            End If
        End While
        Return Receive_Msg
    End Function
End Class
